package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;

	@Autowired
	private VodService vodService;

	@Autowired
	private AlbumInfoMapper albumInfoMapper;

	@Autowired
	private TrackStatMapper trackStatMapper;

	@Autowired
	private UserInfoFeignClient userInfoFeignClient;

	@Autowired
	private AlbumInfoService albumInfoService;

	@Override
	public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> trackListVoPage, TrackInfoQuery trackInfoQuery) {
		//  调用mapper 层方法.
		return trackInfoMapper.selectUserTrackPage(trackListVoPage,trackInfoQuery);
	}

	/**
	 * 查询声音列表
	 * @param trackId 	声音ID
	 * @param trackCount 购买集数
	 * @return
	 */
	@Override
	public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount) {
		//	声明一个集合来存储声音
		List<TrackInfo> trackInfoList = new ArrayList<>();
		//	获取到当前声音对象. select * from track_info where album_id = 1; TrackInfo trackInfo = this.getById(trackId);
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		//	获取已支付的声音Id 列表
		Result<List<Long>> userPaidTrackListResult = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
		Assert.notNull(userPaidTrackListResult,"已购买声音Id结果集为空");
		List<Long> trackIdList = userPaidTrackListResult.getData();
		//	获取到订单明细.
		if (trackCount.intValue()>0){
			//	select * from track_info track where track.album_id = 1 and track.order_num > ?  order by track.order_num asc limit ?
			LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
			wrapper.eq(TrackInfo::getAlbumId,trackInfo.getAlbumId());
			wrapper.gt(TrackInfo::getOrderNum,trackInfo.getOrderNum());
			//	判断是否有已购买的声音Id
			if (!CollectionUtils.isEmpty(trackIdList)){
				wrapper.notIn(TrackInfo::getId,trackIdList);
			}
			wrapper.orderByAsc(TrackInfo::getOrderNum);
			wrapper.last(" limit "+ trackCount);
			//	返回数据
			trackInfoList = trackInfoMapper.selectList(wrapper);
		} else {
			//	说明是购买的本集
			trackInfoList.add(trackInfo);
		}
		//	返回数据
		return trackInfoList;
	}

	@Override
	public List<Map<String, Object>> findUserTrackPaidList(Long trackId) {
		//	根据声音Id 查询声音对象
		//	select order_num from track_info where id = ?
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		//	根据专辑 Id 获取到声音列表：
		//	获取用户已购买的声音Id列表。10 或 0
		Result<List<Long>> trackIdListResult = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
		Assert.notNull(trackIdListResult,"声音Id集合为空");
		//	获取声音Id列表
		List<Long> trackIdList = trackIdListResult.getData();
		// 所有购买列表 select * from track_info track where track.order_num > (select order_num from track_info where id = ?) and track.album_id = ?
		LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(TrackInfo::getAlbumId,trackInfo.getAlbumId());
		wrapper.gt(TrackInfo::getOrderNum,trackInfo.getOrderNum());
		List<TrackInfo> trackInfoList = trackInfoMapper.selectList(wrapper);
		//	数据转换：trackInfoList trackIdAllList
		List<Long> trackIdAllList = trackInfoList.stream().map(TrackInfo::getId).collect(Collectors.toList());
		//	需要知道哪些需要付费的声音Id列表.
		//	声明一个集合来存储需要付费的声音Id 列表
		List<Long> trackIdNoReaptList = new ArrayList<>();
		//	说明这个用户没有购买这个专辑中的声音Id  trackIdList = 0
		if (CollectionUtils.isEmpty(trackIdList)){
			//	获取收费声音Id列表
			trackIdNoReaptList = trackIdAllList;
		} else {
			//	说明这个用户有购买这个专辑中的声音Id   trackIdList = 10
			trackIdNoReaptList = trackIdAllList.stream().filter(id -> !trackIdList.contains(id)).collect(Collectors.toList());
		}

		//	获取到专辑对象
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		//	声明一个list 集合来存储map 集合
		List<Map<String,Object>> list = new ArrayList<>();
		//	判断
		if (trackIdNoReaptList.size()>=0){
			//	给map 集合赋值：
			Map<String, Object> map = new HashMap<>();
			map.put("name","本集"); // 显示文本
			map.put("price",albumInfo.getPrice()); // 专辑声音对应的价格
			map.put("trackCount",0); // 记录购买集数
			//	添加map 到集合中。
			list.add(map);
		}
		//	处理后10  trackIdNoReaptList.size() = 9  trackIdNoReaptList.size() = 18
		if (trackIdNoReaptList.size()>0 && trackIdNoReaptList.size() <= 10){
			//	获取到集合长度
			int count = trackIdNoReaptList.size();
			//	给map 集合赋值：
			Map<String, Object> map = new HashMap<>();
			map.put("name","后"+count+"集"); // 显示文本
			map.put("price",albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(count)))); // 专辑声音对应的价格
			map.put("trackCount",count); // 记录购买集数
			//	添加map 到集合中。
			list.add(map);
		}
		if (trackIdNoReaptList.size()>10){
			//	给map 集合赋值：
			Map<String, Object> map = new HashMap<>();
			map.put("name","后10集"); // 显示文本
			map.put("price",albumInfo.getPrice().multiply(new BigDecimal("10"))); // 专辑声音对应的价格
			map.put("trackCount",10); // 记录购买集数
			//	添加map 到集合中。
			list.add(map);
		}
		//	处理后20  trackIdNoReaptList.size() = 18
		if (trackIdNoReaptList.size()>10 && trackIdNoReaptList.size() <= 20){
			//	获取到集合长度
			int count = trackIdNoReaptList.size();
			//	给map 集合赋值：
			Map<String, Object> map = new HashMap<>();
			map.put("name","后"+count+"集"); // 显示文本
			map.put("price",albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(count)))); // 专辑声音对应的价格
			map.put("trackCount",count); // 记录购买集数
			//	添加map 到集合中。
			list.add(map);
		}
		if (trackIdNoReaptList.size()>20){
			//	给map 集合赋值：
			Map<String, Object> map = new HashMap<>();
			map.put("name","后20集"); // 显示文本
			map.put("price",albumInfo.getPrice().multiply(new BigDecimal("20"))); // 专辑声音对应的价格
			map.put("trackCount",20); // 记录购买集数
			//	添加map 到集合中。
			list.add(map);
		}

		//后30集
		if(trackIdNoReaptList.size() > 20 && trackIdNoReaptList.size() <= 30) {
			Map<String, Object> map = new HashMap<>();
			int count = trackIdNoReaptList.size();
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
			map.put("name", "后"+count+"集");
			map.put("price", price);
			map.put("trackCount", count);
			list.add(map);
		}
		if(trackIdNoReaptList.size() > 30) {
			Map<String, Object> map = new HashMap<>();
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(30));
			map.put("name", "后30集");
			map.put("price", price);
			map.put("trackCount", 30);
			list.add(map);
		}
		//后50集
		if(trackIdNoReaptList.size() > 30 && trackIdNoReaptList.size() <= 50) {
			Map<String, Object> map = new HashMap<>();
			int count = trackIdNoReaptList.size();
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
			map.put("name", "后"+count+"集");
			map.put("price", price);
			map.put("trackCount", count);
			list.add(map);
		}
		// 最多购买50集;
		if(trackIdNoReaptList.size() > 50) {
			Map<String, Object> map = new HashMap<>();
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(50));
			map.put("name", "后50集");
			map.put("price", price);
			map.put("trackCount", 50);
			list.add(map);
		}
		//	返回map 集合数据
		return list;
	}

	@Override
	public TrackStatVo getTrackStatVo(Long trackId) {
		return trackInfoMapper.selectTrackStat(trackId);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateStat(Long albumId, Long trackId, String statType, Integer count) {
		//	更新声音的播放量：
		trackInfoMapper.updateStat(trackId, statType, count);
		//	判断
		if (statType.equals(SystemConstant.TRACK_STAT_PLAY)){
			//	调用更新专辑播放量方法.
			albumInfoService.updateStat(albumId, SystemConstant.ALBUM_STAT_PLAY, count);
		}
	}

	/**
	 * 查看专辑对应的声音列表
	 * @param userId
	 * @param albumId
	 * @param page
	 * @return
	 */
	@Override
	public IPage<AlbumTrackListVo> findAlbumTrackPage(Long userId, Long albumId, Page<AlbumTrackListVo> page) {
		//	1.	先根据专辑Id与分页条件获取到当前声音列表集合
		IPage<AlbumTrackListVo> pageInfo = trackInfoMapper.selectAlbumTrackPage(albumId,page);
		//	获取专辑对象
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		Assert.notNull(albumInfo,"专辑为空");
		//	2.	判断用户是否为空
		if (null == userId){
			//	判断专辑的类型:0101-免费 0102-vip付费 0103-付费
			if (!albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_FREE)){
				//	除去试听集数都要显示付费标识！
				List<AlbumTrackListVo> albumTrackNeedPaidListVoList = pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum().intValue() > albumInfo.getTracksForFree().intValue()).collect(Collectors.toList());
				//	需要循环遍历赋值isShowPaidMark=true
				if (!CollectionUtils.isEmpty(albumTrackNeedPaidListVoList)){
					albumTrackNeedPaidListVoList.forEach(albumTrackListVo -> {
						//	赋值显示付费标识
						albumTrackListVo.setIsShowPaidMark(true);
					});
				}
			}
		} else {
			//	当前用户已登录
			//	声明一个变量来记录是否需要付费标识
			boolean isNeedPaid = false;
			//	专辑类型：0102-vip付费
			if (albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_VIPFREE)){
				//	判断用户类型：
				Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
				Assert.notNull(userInfoVoResult,"用户结果集为空");
				UserInfoVo userInfoVo = userInfoVoResult.getData();
				Assert.notNull(userInfoVo,"用户为空");
				//	用户属于普通|非VIP用户
				if (userInfoVo.getIsVip().intValue() == 0){
					//	需要付费
					isNeedPaid = true;
				}
				//	用户属于vip，但是vip已过期
				if (userInfoVo.getIsVip().intValue() == 1 && userInfoVo.getVipExpireTime().before(new Date())){
					//	需要付费
					isNeedPaid = true;
				}
				// 0103-付费
			} else if (albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_REQUIRE)){
				//	需要付费
				isNeedPaid = true;
			}
			//	统一处理付费标识的请求：
			if (isNeedPaid){
				//	属于付费情况.
				//	除去试听集数都要显示付费标识！
				List<AlbumTrackListVo> albumTrackNeedPaidListVoList = pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum().intValue() > albumInfo.getTracksForFree().intValue()).collect(Collectors.toList());
				//	判断
				Assert.notNull(albumTrackNeedPaidListVoList,"付费声音集合为空");
				//	获取到需要付费的声音Id 集合列表
				List<Long> trackIdList = albumTrackNeedPaidListVoList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
				//	需要再考虑，当前这个用户是否购买过声音！ Map<Long,Integer> map
				Result<Map<Long,Integer>> mapResult =  userInfoFeignClient.userIsPaidTrack(albumId,trackIdList);
				Assert.notNull(mapResult,"返回结果集为空");
				//	判断 map.put(trackId,1);购买过  map.put(trackId,0);没有购买
				Map<Long,Integer> map = mapResult.getData();
				Assert.notNull(map,"map结果集为空");
				//	albumTrackNeedPaidListVoList 6-55
				albumTrackNeedPaidListVoList.forEach(albumTrackListVo -> {
					//	判断是否需要付费
					boolean isBuy = map.get(albumTrackListVo.getTrackId())==1?false:true;
					albumTrackListVo.setIsShowPaidMark(isBuy);
				});
			}
		}
		//	返回数据
		return pageInfo;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeTrackInfo(Long trackId) {
		//	通过声音Id 来获取声音对象
		TrackInfo trackInfo = this.getById(trackId);
		//	track_info 数据库都采用逻辑删除.
		trackInfoMapper.deleteById(trackId);
		//	album_info 减少专辑包含的声音总数.
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		if (null != albumInfo){
			//	总集数减1
			albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
			//	调用更新方法
			albumInfoMapper.updateById(albumInfo);
		}
		//	track_stat
		trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId,trackId));
		//	media 删除云点播中声音记录。
		vodService.removeTrack(trackInfo.getMediaFileId());

	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
		//	track_info
		//	如何判断用户是否修改过声音?
		TrackInfo trackInfo = this.getById(trackId);
		//	先获取到原来的声音Id -- 从数据库中查询的数据.
		String mediaFileId = trackInfo.getMediaFileId();
		//	做一个属性赋值
		BeanUtils.copyProperties(trackInfoVo,trackInfo);
		//	判断 mediaFileId：从数据库中查询的数据  trackInfoVo.getMediaFileId() 页面传递的数据
		if (!mediaFileId.equals(trackInfoVo.getMediaFileId())){
			//	调用处理声音的服务层对象
			TrackMediaInfoVo trackMediaInfo = vodService.getTrackMediaInfo(trackInfoVo.getMediaFileId());
			if (null == trackMediaInfo){
				throw new GuiguException(ResultCodeEnum.VOD_FILE_ID_ERROR);
			}
			//	说明你修改过了.
			trackInfo.setMediaType(trackMediaInfo.getType());
			trackInfo.setMediaUrl(trackMediaInfo.getMediaUrl());
			trackInfo.setMediaDuration(trackMediaInfo.getDuration());
			trackInfo.setMediaSize(trackInfo.getMediaSize());

			//	修改声音播放量.
			LambdaUpdateWrapper<TrackStat> wrapper = new LambdaUpdateWrapper<>();
			// update track_stat track set track.stat_num = 0 where track.track_id = 51956;
			wrapper.eq(TrackStat::getTrackId,trackId);
			TrackStat trackStat = new TrackStat();
			trackStat.setStatNum(0);
			trackStatMapper.update(trackStat,wrapper);
		}
		//	修改声音。
		this.updateById(trackInfo);
	}

	@Override
	public TrackInfo getTrackInfo(Long trackId) {
		return trackInfoMapper.selectById(trackId);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
		//	创建声音对象  track_info
		TrackInfo trackInfo = new TrackInfo();
		//	属性拷贝
		BeanUtils.copyProperties(trackInfoVo,trackInfo);
		//	user_id
		//	trackInfo.setUserId(userId);
		//	默认值用户Id 为 1
		trackInfo.setUserId(1l);
		//	orderNum 设置声音的排序！
		int orderNum = 1;
		//	根据专辑Id 查询声音表中的order_num 值。select order_num from track_info where album_id = 1602 order by id desc limit 1;
		LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(TrackInfo::getAlbumId,trackInfoVo.getAlbumId());
		wrapper.orderByDesc(TrackInfo::getId);
		wrapper.last(" limit 1 ");
		wrapper.select(TrackInfo::getOrderNum);
		TrackInfo preTrackInfo = trackInfoMapper.selectOne(wrapper);
		//	判断当前这张专辑下是否有声音。
		if (null != preTrackInfo){
			orderNum = preTrackInfo.getOrderNum() + 1;
		}
		//	赋值声音的顺序值。
		trackInfo.setOrderNum(orderNum);
		//	赋值流媒体信息。media_duration , media_size ,media_type, media_url - 看api官网文档.
		TrackMediaInfoVo trackMediaInfoVo = vodService.getTrackMediaInfo(trackInfoVo.getMediaFileId());
		trackInfo.setMediaSize(trackMediaInfoVo.getSize());
		trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
		trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
		trackInfo.setMediaType(trackMediaInfoVo.getType());
		//	保存数据
		trackInfoMapper.insert(trackInfo);

		//	修改专辑中的声音总数 album_info
		//	先获取到专辑对应的声音总数。
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
		//	判断对象是否为空
		if (null != albumInfo){
			//	专辑总数+1
			albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()+1);
			//	更新专辑总数
			albumInfoMapper.updateById(albumInfo);
		}
		//	track_stat 声音统计
		this.saveTrackStat(trackInfo.getId(),SystemConstant.TRACK_STAT_PLAY);
		this.saveTrackStat(trackInfo.getId(),SystemConstant.TRACK_STAT_COLLECT);
		this.saveTrackStat(trackInfo.getId(),SystemConstant.TRACK_STAT_PRAISE);
		this.saveTrackStat(trackInfo.getId(),SystemConstant.TRACK_STAT_COMMENT);

	}

	private void saveTrackStat(Long trackId, String statPlay) {
		//	创建对象
		TrackStat trackStat = new TrackStat();
		//	赋值
		trackStat.setTrackId(trackId);
		trackStat.setStatNum(0);
		trackStat.setStatType(statPlay);
		//	插入数据
		trackStatMapper.insert(trackStat);
	}
}
